# == Schema Information
#
# Table name: orders
#
#  id              :integer          not null, primary key
#  user_id         :integer
#  address_id      :integer
#  order_no        :string
#  amount          :integer
#  total_money     :decimal(10, 2)
#  status          :integer          default(0)
#  workflow_state  :string
#  channel_id      :integer
#  order_type      :integer          default("normal")
#  reserve_id      :integer
#  tail_pay        :decimal(10, 2)
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#  payment_at      :datetime
#  chuang_order_no :string
#  invoice_id      :integer
#

class Order < ApplicationRecord

  enum order_type: [:normal, :surveying]

  belongs_to :user
  belongs_to :address
  belongs_to :invoice

  has_one :payment
  has_one :order_attachment

  has_many :order_items
  has_many :order_histories
  belongs_to :reserve

  before_create :gen_order_no

  include Workflow
  include WorkflowPlus

  def new_date
    self.created_at.to_s(:db)
  end

  def attachment_img
    self.order_attachment
  end

  def order_survey
    self.reserve.survey_fee  unless self.normal?
  end

  def as_json(options={})
    # super({include: [:order_items], methods: [:all_order_items]}.merge(options))
    super({include: [:user], methods: [:new_date, :all_order_items, :full_address, :attachment_img, :order_survey]}.merge(options))
  end

  def full_address
    if self.normal?
      self.address.as_json
    else
      self.reserve.address.as_json
    end
  end

  def all_order_items
    self.order_items.as_json
  end

  workflow do

    state :unpaid do
      event :down_pay, :transitions_to => :down_payment
      event :complete_pay, :transitions_to => :paid
      event :fail, :transitions_to => :failed
    end

    state :paid do
    end

    state :down_payment do
      event :to_survey, :transitions_to => :survey_pending
      event :fail, :transitions_to => :failed
    end

    state :survey_pending do
      event :complete_survey, :transitions_to => :survey_completed
    end

    state :survey_completed do
      event :tail_pay, :transitions_to => :tail_payment
    end

    state :tail_payment do
      event :to_install, :transitions_to => :install_pending
      event :fail, :transitions_to => :failed
    end

    state :install_pending do
      event :complete, :transitions_to => :completed
    end

    state :failed
    state :completed

  end

  def subtotal
    order_items.collect { |oi| oi.valid? ? (oi.quantity * oi.unit_price) : 0 }.sum
  end

  def self.create_order_from_carts! user, address, *shopping_carts
    shopping_carts.flatten!
    address_attrs = address.attributes.except!("id", "created_at", "updated_at")

    order = nil

    transaction do
      order_address = user.addresses.create!(address_attrs)


      shopping_carts.group_by(&:channel_id).each do |channel_id, members|

        order = user.orders.build
        order.address_id = order_address.id
        members.each do |shopping_cart|
          order.order_items << OrderItem.new(
            product: shopping_cart.product,
            unit_price: shopping_cart.product.price,
            quantity: shopping_cart.amount,
            total_price: shopping_cart.amount * shopping_cart.product.price
          )
        end

        order.channel_id = channel_id
        order.total_money = order.order_items.collect { |oi| oi.valid? ? (oi.quantity * oi.unit_price) : 0 }.sum
        order.amount = order.order_items.collect { |oi| oi.valid? ? (oi.quantity) : 0 }.sum
        order.save!
      end

      shopping_carts.map(&:destroy!)
    end

    order
  end

  def self.create_order_from_reserving! user, address, reserve_id, channel_id=Channel.first.id
    order = user.orders.build
    transaction do
      survey_fee = SurveyFee.find(Reserve.find(reserve_id).survey_fee_id)

      order.order_items << OrderItem.new(
        unit_price: survey_fee.amount,
        is_not_surveying: true,
        quantity: 1,
        total_price: survey_fee.amount
      )

      order.order_type = Order.order_types[:surveying]
      order.reserve_id = reserve_id
      order.channel_id = channel_id
      order.total_money = survey_fee.amount
      order.amount = 1
      OrderService.log_order_history(order)
    end

    order

  end

  private

  def gen_order_no
    self.order_no = RandomCode.generate_order_uuid
  end

  def format_amount
    self.amount = self.amount * 100
  end

end
